"""
@Author：十
@Time：2025/8/5 9:05
@FileName：diagnose.py
@Description：诊断运行状态
"""
import joblib
import numpy as np
import pandas as pd
import os
import sys
from loguru import logger


class Diagnose(object):
    def __init__(self):
        pass

    # 加载两个模型并得出”内部温度“、”异常温度“数据
    # 根据”内部温度“判断”异常值“是否在正常范围中
    # 返回内部温度值及状态
    def diagnose(self, new_sample):
        try:
            inner_temperature = self.load_and_predict(new_sample, 'model_without_current.pkl')
            except_temperature = self.load_and_predict(new_sample, 'model_exception.pkl')
            if inner_temperature is not None and except_temperature is not None:
                if int(inner_temperature) < 120:
                    return inner_temperature, '正常'
                else:
                    return inner_temperature, '异常'
            else:
                return None, '异常'
        except Exception as e:
            print(f"诊断失败: {e}")
            logger.critical(f'诊断失败：{e}')
            return None, '异常'

    # 加载模型并预测单一样本
    # 输入数据是：环境温度、外部温度的数组
    def load_and_predict(self, new_sample, model):
        try:
            # 获取模型文件的绝对路径
            model_path = self.resource_path(model)

            # 检查模型文件是否存在
            if not os.path.exists(model_path):
                logger.critical(f'模型文件不存在: {model_path}')
                return None

            # 没有载流量的模型
            saved_data = joblib.load(model_path)
            model = saved_data['model']
            scaler_X = saved_data['scaler_X']
            scaler_y = saved_data['scaler_y']
            feature_names = saved_data['feature_names']

            # 检查特征数量是否匹配
            if len(new_sample) != len(feature_names):
                raise ValueError(f"输入特征数量应为 {len(feature_names)}, 实际输入 {len(new_sample)}")

            # 检查输入数据是否包含无效值
            if any(x is None or (isinstance(x, float) and np.isnan(x)) for x in new_sample):
                logger.warning(f'输入数据包含无效值: {new_sample}')
                return None

            # 创建带有特征名称的DataFrame
            sample_df = pd.DataFrame([new_sample], columns=feature_names)

            # 执行归一化和预测
            normalized_sample = scaler_X.transform(sample_df)
            pred_scaled = model.predict(normalized_sample)
            predicted_value = scaler_y.inverse_transform(pred_scaled.reshape(-1, 1))

            result = predicted_value.flatten()[0]
            # 检查预测结果是否有效
            if np.isnan(result) or np.isinf(result):
                logger.warning('预测结果无效')
                return None

            return result

        except FileNotFoundError as e:
            print(f"模型文件未找到: {e}")
            logger.critical(f'模型文件未找到: {e}')
            return None
        except ValueError as e:
            print(f"输入值错误: {e}")
            logger.critical(f'输入值错误: {e}')
            return None
        except Exception as e:
            print(f"预测失败: {e}")
            logger.critical(f'预测失败：{e}')
            return None

    def resource_path(self, relative_path):
        """获取资源文件的绝对路径"""
        try:
            # PyInstaller创建临时文件夹，将路径存储在_MEIPASS中
            base_path = sys._MEIPASS
        except Exception:
            base_path = os.path.abspath(".")

        return os.path.join(base_path, relative_path)

